use crate::core::vec3::*;
use crate::core::hittable::*;
use crate::core::ray::*;
use std::rc::Rc;
use crate::core::material::*;


pub struct Sphere{
    center: Point3,
    radius: f64,
    mat_ptr: Rc<dyn Material>,
}

impl Sphere{
    // pub fn new() -> Sphere {
    //     Sphere{center:Point3::new(), radius:0_f64, mat_ptr: }
    // }
    pub fn from(cen: &Point3, r: f64, m: Rc<dyn Material>) -> Sphere{
        Sphere{center: *cen, radius:r, mat_ptr: m}
    }
}

impl Hittable for Sphere{
    // pub fn hit(r: &Ray, t_min: f64, t_max: f64, rec: &HitRecord) -> Option<HitRecord>{
    fn hit(&self, r: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord>{
        // 公式为t^2诚意
        let oc = r.origin() - &self.center;
        let a = r.direction().length_squared();
        let half_b = dot(&oc, &r.direction());
        let c = oc.length_squared() - &self.radius*&self.radius;
        let discriminant = half_b * half_b - a*c;

        if discriminant < 0_f64 {
            return None;
        }
        let sqrt = discriminant.sqrt();

        // 找到最近的
        let mut root = (-half_b - sqrt) / a;
        if root < t_min || t_max < root {
            root = (-half_b + sqrt)/a;
            if root < t_min || t_max < root {
                return None;
            }
        }
        let mut temp_record = HitRecord{
            t : root,
            p : r.at(root),
            normal : None,
            front_face : None,
            mat_ptr: Rc::clone(&self.mat_ptr),
        };
        let outward_normal = &(&temp_record.p - &self.center) / self.radius;
        temp_record.set_face_front_and_noraml(& r,  &outward_normal);
        Some(temp_record)
    }
}